package api

import (
	"net/http"
	"strconv"

	"github.com/gin-gonic/gin"
	"github.com/jiedan/student-web/server/model"
	"gorm.io/gorm"
)

// CourseSelectionHandler 选课处理器
type CourseSelectionHandler struct {
	DB *gorm.DB
}

// NewCourseSelectionHandler 创建选课处理器
func NewCourseSelectionHandler(db *gorm.DB) *CourseSelectionHandler {
	return &CourseSelectionHandler{DB: db}
}

// GetStudentCourses 获取学生已选课程
func (h *CourseSelectionHandler) GetStudentCourses(c *gin.Context) {
	studentID, err := strconv.ParseUint(c.Param("student_id"), 10, 32)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid student ID"})
		return
	}

	// 检查学生是否存在
	var student model.Student
	result := h.DB.First(&student, studentID)
	if result.Error != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "Student not found"})
		return
	}

	// 获取学生选课记录
	var selections []model.CourseSelection
	result = h.DB.Where("student_id = ?", studentID).Find(&selections)
	if result.Error != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get course selections"})
		return
	}

	// 获取课程详情
	var courses []model.Course
	for _, selection := range selections {
		var course model.Course
		result = h.DB.Preload("Teacher.User").First(&course, selection.CourseID)
		if result.Error == nil {
			courses = append(courses, course)
		}
	}

	c.JSON(http.StatusOK, courses)
}

// GetCourseStudents 获取选择某课程的学生
func (h *CourseSelectionHandler) GetCourseStudents(c *gin.Context) {
	courseID, err := strconv.ParseUint(c.Param("course_id"), 10, 32)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid course ID"})
		return
	}

	// 检查课程是否存在
	var course model.Course
	result := h.DB.First(&course, courseID)
	if result.Error != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "Course not found"})
		return
	}

	// 获取选课记录
	var selections []model.CourseSelection
	result = h.DB.Where("course_id = ?", courseID).Find(&selections)
	if result.Error != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get course selections"})
		return
	}

	// 获取学生详情
	var students []model.Student
	for _, selection := range selections {
		var student model.Student
		result = h.DB.Preload("User").First(&student, selection.StudentID)
		if result.Error == nil {
			students = append(students, student)
		}
	}

	c.JSON(http.StatusOK, students)
}

// SelectCourseRequest 选课请求
type SelectCourseRequest struct {
	StudentID uint `json:"student_id" binding:"required"`
	CourseID  uint `json:"course_id" binding:"required"`
}

// SelectCourse 学生选课
func (h *CourseSelectionHandler) SelectCourse(c *gin.Context) {
	var req SelectCourseRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request format"})
		return
	}

	// 检查学生是否存在
	var student model.Student
	result := h.DB.First(&student, req.StudentID)
	if result.Error != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "Student not found"})
		return
	}

	// 检查课程是否存在
	var course model.Course
	result = h.DB.First(&course, req.CourseID)
	if result.Error != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "Course not found"})
		return
	}

	// 检查是否已经选过这门课
	var existingSelection model.CourseSelection
	result = h.DB.Where("student_id = ? AND course_id = ?", req.StudentID, req.CourseID).First(&existingSelection)
	if result.Error == nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Student has already selected this course"})
		return
	}

	// 检查课程容量
	var selectionCount int64
	h.DB.Model(&model.CourseSelection{}).Where("course_id = ?", req.CourseID).Count(&selectionCount)
	if int(selectionCount) >= course.Capacity {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Course is full"})
		return
	}

	// 创建选课记录
	selection := model.CourseSelection{
		StudentID: req.StudentID,
		CourseID:  req.CourseID,
	}

	result = h.DB.Create(&selection)
	if result.Error != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to select course"})
		return
	}

	c.JSON(http.StatusCreated, gin.H{"message": "Course selected successfully"})
}

// DropCourseRequest 退课请求
type DropCourseRequest struct {
	StudentID uint `json:"student_id" binding:"required"`
	CourseID  uint `json:"course_id" binding:"required"`
}

// DropCourse 学生退课
func (h *CourseSelectionHandler) DropCourse(c *gin.Context) {
	var req DropCourseRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request format"})
		return
	}

	// 检查选课记录是否存在
	var selection model.CourseSelection
	result := h.DB.Where("student_id = ? AND course_id = ?", req.StudentID, req.CourseID).First(&selection)
	if result.Error != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "Course selection not found"})
		return
	}

	// 开始事务
	tx := h.DB.Begin()

	// 删除成绩记录（如果有）
	if err := tx.Where("student_id = ? AND course_id = ?", req.StudentID, req.CourseID).Delete(&model.Grade{}).Error; err != nil {
		tx.Rollback()
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to delete grade"})
		return
	}

	// 删除选课记录
	if err := tx.Delete(&selection).Error; err != nil {
		tx.Rollback()
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to drop course"})
		return
	}

	// 提交事务
	if err := tx.Commit().Error; err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to commit transaction"})
		return
	}

	c.JSON(http.StatusOK, gin.H{"message": "Course dropped successfully"})
}